home *** CD-ROM | disk | FTP | other *** search
/ Aminet 3 / Aminet 3 - July 1994.iso / Aminet / dev / gui / intuigen2.lzh / IntuiGen / IntuiGenLibs / IGFR.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-22  |  30.1 KB  |  1,453 lines

  1. /*
  2. IGFR.c
  3.  
  4. (C) Copyright 1993 Justin Miller
  5.     This file is part of the IntuiGen package.
  6.     Use of this code is pursuant to the license outlined in
  7.     COPYRIGHT.txt, included with the IntuiGen package.
  8.  
  9.     As per COPYRIGHT.txt:
  10.  
  11.     1)  This file may be freely distributed providing that
  12.         it is unmodified, and included in a complete IntuiGen
  13.         2.0 package (it may not be distributed alone).
  14.  
  15.     2)  Programs using this code may not be distributed unless
  16.         their author has paid the Shareware fee for IntuiGen 2.0.
  17. */
  18.  
  19.  
  20. #include <exec/exec.h>
  21. #include <intuition/intuition.h>
  22. #include <dos/dos.h>
  23. #include <dos/dosextens.h>
  24. #include <IntuiGen/IntuiGen.h>
  25. #include <IntuiGen/IGSBox.h>
  26. #include <clib/intuition_protos.h>
  27. #include <clib/dos_protos.h>
  28. #include <clib/exec_protos.h>
  29.  
  30. extern struct DosLibrary *DosBase;
  31. void IGFRQuit ();
  32.  
  33. #define DEVS 0
  34. #define PARENT 1
  35. #define OK 2
  36. #define CANCEL 3
  37. #define EXT 4
  38. #define FILE 5
  39. #define UP 6
  40. #define DOWN 7
  41. #define SCROLL 8
  42.  
  43.  
  44. #define DIR 1
  45. #define DISPLAYED 2
  46. #define SELECTED 4
  47.  
  48. /* #define INCLUDEARROWDATA */
  49. /*  When linking this to other modules, you will often have arrow data
  50.     already defined.  Also, you can define (globally) UpArrowData and
  51.     DownArrowData as being pointers to the info in chip ram.  You can
  52.     do this either by allocating chip ram and copying the arrow data into
  53.     it or adding the __chip identifier supported by most compilers, as follows:
  54.  
  55.     __chip USHORT UpArrowData[] = {....}
  56. */
  57.  
  58. #ifdef INCLUDEARROWDATA
  59.  
  60. static USHORT UpArrowData[] = {
  61.  
  62.     /* BitPlane 0 */
  63.  
  64.     0x0000,
  65.     0x0004,
  66.     0x0004,
  67.     0x0304,
  68.     0x0784,
  69.     0x0CC4,
  70.     0x1864,
  71.     0x1024,
  72.     0x0004,
  73.     0x0004,
  74.     0xFFFC,
  75.  
  76.     /* BitPlane 1 */
  77.  
  78.     0xFFFF,
  79.     0x8000,
  80.     0x8000,
  81.     0x8000,
  82.     0x8000,
  83.     0x8000,
  84.     0x8000,
  85.     0x8000,
  86.     0x8000,
  87.     0x8000,
  88.     0x0000
  89. };
  90.  
  91. static USHORT DownArrowData[] = {
  92.  
  93.     /* BitPlane 0 */
  94.  
  95.     0x0000,
  96.     0x0004,
  97.     0x0004,
  98.     0x1024,
  99.     0x1864,
  100.     0x0CC4,
  101.     0x0784,
  102.     0x0304,
  103.     0x0004,
  104.     0x0004,
  105.     0xFFFC,
  106.  
  107.     /* BitPlane 1 */
  108.  
  109.     0xFFFF,
  110.     0x8000,
  111.     0x8000,
  112.     0x8000,
  113.     0x8000,
  114.     0x8000,
  115.     0x8000,
  116.     0x8000,
  117.     0x8000,
  118.     0x8000,
  119.     0x0000
  120. };
  121.  
  122. #else
  123.  
  124. extern USHORT *UpArrowData,*DownArrowData;
  125.  
  126. #endif /* INCLUDEARROWDATA */
  127.  
  128. static struct TextAttr attr=
  129. {
  130.     "topaz.font",TOPAZ_EIGHTY,NULL,FPF_ROMFONT
  131. };
  132.  
  133. static struct IntuiText IGFRExtText =
  134. {
  135.     1,0,
  136.     JAM2,
  137.     -42,0,
  138.     &attr,
  139.     (UBYTE *)"Ext:",
  140.     NULL
  141. };
  142.  
  143. static SHORT IGFRExtValues1[] = {0,11,0,0,50,0};
  144.  
  145. static SHORT IGFRExtValues2[] = {0,11,50,11,50,0};
  146.  
  147. static struct Border IGFRExtB2 =
  148. {
  149.     -2,-2,
  150.     2,0,
  151.     JAM1,
  152.     3,
  153.     IGFRExtValues1,
  154.     NULL
  155. };
  156.  
  157. static struct Border IGFRExtB1 =
  158. {
  159.     -2,-2,
  160.     1,0,
  161.     JAM1,
  162.     3,
  163.     IGFRExtValues2,
  164.     &IGFRExtB2
  165. };
  166.  
  167. static struct Gadget IGFRExt =
  168. {
  169.     NULL,
  170.     102,109,
  171.     47,10,
  172.     GFLG_GADGHCOMP,
  173.     GACT_RELVERIFY | GACT_IMMEDIATE,
  174.     GTYP_STRGADGET,
  175.     (APTR)&IGFRExtB1,
  176.     NULL,
  177.     &IGFRExtText,
  178.     NULL,
  179.     NULL,
  180.     0,
  181.     NULL
  182. };
  183.  
  184. static SHORT IGFRBoxValues1[] = {0,122,0,0,310,0,309,1,1,1,1,121};
  185.  
  186. static SHORT IGFRBoxValues2[] = {0,122,310,122,310,0,309,1,309,121,1,121};
  187.  
  188. static struct Border IGFRBoxB2 =
  189. {
  190.     5,13,
  191.     2,0,
  192.     JAM1,
  193.     6,
  194.     IGFRBoxValues1,
  195.     NULL
  196. };
  197.  
  198. static struct Border IGFRBoxB1 =
  199. {
  200.     5,13,
  201.     1,0,
  202.     JAM1,
  203.     6,
  204.     IGFRBoxValues2,
  205.     &IGFRBoxB2
  206. };
  207.  
  208. static struct IntuiText IGFRCancelText =
  209. {
  210.     1,0,
  211.     JAM2,
  212.     10,3,
  213.     &attr,
  214.     (UBYTE *)"Cancel",
  215.     NULL
  216. };
  217.  
  218. static SHORT IGFRCancelValues1[] = {0,12,0,0,68,0,67,1,1,1,1,11};
  219.  
  220. static SHORT IGFRCancelValues2[] = {0,12,68,12,68,0,67,1,67,11,1,11};
  221.  
  222. static struct Border IGFRCancelB2 =
  223. {
  224.     0,0,
  225.     2,0,
  226.     JAM1,
  227.     6,
  228.     IGFRCancelValues1,
  229.     NULL
  230. };
  231.  
  232. static struct Border IGFRCancelB1 =
  233. {
  234.     0,0,
  235.     1,0,
  236.     JAM1,
  237.     6,
  238.     IGFRCancelValues2,
  239.     &IGFRCancelB2
  240. };
  241.  
  242. static struct Border IGFRCancelSelectedB2 =
  243. {
  244.     0,0,
  245.     1,0,
  246.     JAM1,
  247.     6,
  248.     IGFRCancelValues1,
  249.     NULL
  250. };
  251.  
  252. static struct Border IGFRCancelSelectedB1 =
  253. {
  254.     0,0,
  255.     2,0,
  256.     JAM1,
  257.     6,
  258.     IGFRCancelValues2,
  259.     &IGFRCancelSelectedB2
  260. };
  261.  
  262. static struct Gadget IGFRCancel =
  263. {
  264.     &IGFRExt,
  265.     244,121,
  266.     68,12,
  267.     GFLG_GADGHIMAGE,
  268.     GACT_RELVERIFY,
  269.     GTYP_BOOLGADGET,
  270.     (APTR)&IGFRCancelB1,
  271.     (APTR)&IGFRCancelSelectedB1,
  272.     &IGFRCancelText,
  273.     NULL,
  274.     NULL,
  275.     853,
  276.     NULL
  277. };
  278.  
  279. static struct IntuiText IGFROKText =
  280. {
  281.     1,0,
  282.     JAM2,
  283.     10,3,
  284.     &attr,
  285.     (UBYTE *)"OK",
  286.     NULL
  287. };
  288.  
  289. static SHORT IGFROKValues1[] = {0,12,0,0,36,0,35,1,1,1,1,11};
  290.  
  291. static SHORT IGFROKValues2[] = {0,12,36,12,36,0,35,1,35,11,1,11};
  292.  
  293. static struct Border IGFROKB2 =
  294. {
  295.     0,0,
  296.     2,0,
  297.     JAM1,
  298.     6,
  299.     IGFROKValues1,
  300.     NULL
  301. };
  302.  
  303. static struct Border IGFROKB1 =
  304. {
  305.     0,0,
  306.     1,0,
  307.     JAM1,
  308.     6,
  309.     IGFROKValues2,
  310.     &IGFROKB2
  311. };
  312.  
  313. static struct Border IGFROKSelectedB2 =
  314. {
  315.     0,0,
  316.     1,0,
  317.     JAM1,
  318.     6,
  319.     IGFROKValues1,
  320.     NULL
  321. };
  322.  
  323. static struct Border IGFROKSelectedB1 =
  324. {
  325.     0,0,
  326.     2,0,
  327.     JAM1,
  328.     6,
  329.     IGFROKValues2,
  330.     &IGFROKSelectedB2
  331. };
  332.  
  333. static struct Gadget IGFROK =
  334. {
  335.     &IGFRCancel,
  336.     207,121,
  337.     36,12,
  338.     GFLG_GADGHIMAGE,
  339.     GACT_RELVERIFY,
  340.     GTYP_BOOLGADGET,
  341.     (APTR)&IGFROKB1,
  342.     (APTR)&IGFROKSelectedB1,
  343.     &IGFROKText,
  344.     NULL,
  345.     NULL,
  346.     852,
  347.     NULL
  348. };
  349.  
  350. static struct IntuiText IGFRParentText =
  351. {
  352.     1,0,
  353.     JAM2,
  354.     10,3,
  355.     &attr,
  356.     (UBYTE *)"Parent",
  357.     NULL
  358. };
  359.  
  360. static struct Gadget IGFRParent =
  361. {
  362.     &IGFROK,
  363.     234,107,
  364.     68,12,
  365.     GFLG_GADGHIMAGE,
  366.     GACT_RELVERIFY,
  367.     GTYP_BOOLGADGET,
  368.     (APTR)&IGFRCancelB1,
  369.     (APTR)&IGFRCancelSelectedB1,
  370.     &IGFRParentText,
  371.     NULL,
  372.     NULL,
  373.     851,
  374.     NULL
  375. };
  376.  
  377. static struct IntuiText IGFRDevsText =
  378. {
  379.     1,0,
  380.     JAM2,
  381.     10,3,
  382.     &attr,
  383.     (UBYTE *)"Devices",
  384.     NULL
  385. };
  386.  
  387. static SHORT IGFRDevsValues1[] = {0,12,0,0,76,0,75,1,1,1,1,11};
  388.  
  389. static SHORT IGFRDevsValues2[] = {0,12,76,12,76,0,75,1,75,11,1,11};
  390.  
  391. static struct Border IGFRDevsB2 =
  392. {
  393.     0,0,
  394.     2,0,
  395.     JAM1,
  396.     6,
  397.     IGFRDevsValues1,
  398.     NULL
  399. };
  400.  
  401. static struct Border IGFRDevsB1 =
  402. {
  403.     0,0,
  404.     1,0,
  405.     JAM1,
  406.     6,
  407.     IGFRDevsValues2,
  408.     &IGFRDevsB2
  409. };
  410.  
  411. static struct Border IGFRDevsSelectedB2 =
  412. {
  413.     0,0,
  414.     1,0,
  415.     JAM1,
  416.     6,
  417.     IGFRDevsValues1,
  418.     NULL
  419. };
  420.  
  421. static struct Border IGFRDevsSelectedB1 =
  422. {
  423.     0,0,
  424.     2,0,
  425.     JAM1,
  426.     6,
  427.     IGFRDevsValues2,
  428.     &IGFRDevsSelectedB2
  429. };
  430.  
  431. static struct Gadget IGFRDevs =
  432. {
  433.     &IGFRParent,
  434.     157,107,
  435.     76,12,
  436.     GFLG_GADGHIMAGE,
  437.     GACT_RELVERIFY,
  438.     GTYP_BOOLGADGET,
  439.     (APTR)&IGFRDevsB1,
  440.     (APTR)&IGFRDevsSelectedB1,
  441.     &IGFRDevsText,
  442.     NULL,
  443.     NULL,
  444.     850,
  445.     NULL
  446. };
  447.  
  448. static struct IntuiText IGFRFNameText =
  449. {
  450.     1,0,
  451.     JAM2,
  452.     -50,0,
  453.     &attr,
  454.     (UBYTE *)"File:",
  455.     NULL
  456. };
  457.  
  458. static SHORT IGFRFNameValues1[] = {0,11,0,0,250,0};
  459.  
  460. static SHORT IGFRFNameValues2[] = {0,11,250,11,250,0};
  461.  
  462. static struct Border IGFRFNameB2 =
  463. {
  464.     -2,-2,
  465.     2,0,
  466.     JAM1,
  467.     3,
  468.     IGFRFNameValues1,
  469.     NULL
  470. };
  471.  
  472. static struct Border IGFRFNameB1 =
  473. {
  474.     -2,-2,
  475.     1,0,
  476.     JAM1,
  477.     3,
  478.     IGFRFNameValues2,
  479.     &IGFRFNameB2
  480. };
  481.  
  482. static struct Gadget IGFRFName =
  483. {
  484.     &IGFRDevs,
  485.     60,96,
  486.     247,10,
  487.     GFLG_GADGHCOMP,
  488.     GACT_RELVERIFY | GACT_IMMEDIATE,
  489.     GTYP_STRGADGET,
  490.     (APTR)&IGFRFNameB1,
  491.     NULL,
  492.     &IGFRFNameText,
  493.     NULL,
  494.     NULL,
  495.     810,
  496.     NULL
  497. };
  498.  
  499. static struct Image IGFRScrollDownArrowImage =
  500. {
  501.     0,0,
  502.     14,11,
  503.     2,
  504.     DownArrowData,
  505.     3,0,
  506.     NULL
  507. };
  508.  
  509. static struct Gadget IGFRScrollDownArrowGad =
  510. {
  511.     &IGFRFName,
  512.     295,82,
  513.     14,11,
  514.     GFLG_GADGHCOMP | GFLG_GADGIMAGE,
  515.     GACT_RELVERIFY | GACT_IMMEDIATE,
  516.     GTYP_BOOLGADGET,
  517.     (APTR)&IGFRScrollDownArrowImage,
  518.     NULL,
  519.     NULL,
  520.     NULL,
  521.     NULL,
  522.     802,
  523.     NULL
  524. };
  525.  
  526. static struct Image IGFRScrollUpArrowImage =
  527. {
  528.     0,0,
  529.     14,11,
  530.     2,
  531.     UpArrowData,
  532.     3,0,
  533.     NULL
  534. };
  535.  
  536. static struct Gadget IGFRScrollUpArrowGad =
  537. {
  538.     &IGFRScrollDownArrowGad,
  539.     295,70,
  540.     14,11,
  541.     GFLG_GADGHCOMP | GFLG_GADGIMAGE,
  542.     GACT_RELVERIFY | GACT_IMMEDIATE,
  543.     GTYP_BOOLGADGET,
  544.     (APTR)&IGFRScrollUpArrowImage,
  545.     NULL,
  546.     NULL,
  547.     NULL,
  548.     NULL,
  549.     801,
  550.     NULL
  551. };
  552.  
  553. static WORD IGFRScrollKnobBuffer[4];
  554.  
  555. static struct PropInfo IGFRScrollPropInfo =
  556. {
  557.     AUTOKNOB | FREEVERT,0,0,0x0800,0x0800,0,0,0,0,0,0
  558. };
  559.  
  560. static struct Gadget IGFRScroll =
  561. {
  562.     &IGFRScrollUpArrowGad,
  563.     295,17,
  564.     14,52,
  565.     GFLG_GADGHNONE,
  566.     GACT_RELVERIFY | GACT_IMMEDIATE,
  567.     GTYP_PROPGADGET,
  568.     (APTR)IGFRScrollKnobBuffer,
  569.     NULL,
  570.     NULL,
  571.     NULL,
  572.     (APTR)&IGFRScrollPropInfo,
  573.     800,
  574.     NULL
  575. };
  576.  
  577. static struct IGDirEntry *DupEntry (struct IGDirEntry *entry)
  578. {
  579.     struct IGDirEntry *dup;
  580.     UBYTE *fname;
  581.  
  582.     dup=AllocMem(sizeof(struct IGDirEntry)+
  583.     strlen(entry->FileName)+1,MEMF_PUBLIC);
  584.     if (!dup) return (0);
  585.     *dup=*entry;
  586.  
  587.     fname=(UBYTE *)dup;
  588.     fname+=sizeof(struct IGDirEntry);
  589.  
  590.     strcpy (fname,entry->FileName);
  591.     dup->FileName=fname;
  592.  
  593.     return (dup);
  594. }
  595.  
  596. struct IGDirEntry *DupDirList(struct IGFileRequest *fr,ULONG flags)
  597. {
  598.     struct IGDirEntry *first=0,*current,*de;
  599.     ULONG copyde;
  600.  
  601.     for (de=fr->First;de;de=de->Next) {
  602.     copyde=1;
  603.     if ( (de->Flags & IGDE_DISPLAYED) && (flags & IGDE_NOTDISPLAYED) )
  604.         copyde=0;
  605.     if ( (de->Flags & IGDE_SELECTED) && (flags & IGDE_NOTSELECTED) )
  606.         copyde=0;
  607.     if ( !(de->Flags & IGDE_SELECTED) && (flags & IGDE_SELECTED) )
  608.         copyde=0;
  609.     if ( !(de->Flags & IGDE_DISPLAYED) && (flags & IGDE_DISPLAYED) )
  610.         copyde=0;
  611.     if ( !(de->Flags & IGDE_DIR) && (flags & IGDE_DIRSONLY) )
  612.         copyde=0;
  613.     if ( (de->Flags & IGDE_DIR) && (flags & IGDE_FILESONLY) )
  614.         copyde=0;
  615.  
  616.     if (copyde) {
  617.         if (first) {
  618.         current->Next=DupEntry(de);
  619.         if (!(current->Next)) break;
  620.         current->Next->Prev=current;
  621.         current=current->Next;
  622.         current->Next=0;
  623.         } else {
  624.         current=first=DupEntry(de);
  625.         if (!first) break;
  626.         first->Prev=first->Next=0;
  627.         }
  628.     }
  629.     }
  630.     return (first);
  631. }
  632.  
  633. void FreeDirList(struct IGDirEntry *de)
  634. {
  635.     struct IGDirEntry *next;
  636.  
  637.     while (de) {
  638.     next=de->Next;
  639.     FreeMem(de,sizeof(struct IGDirEntry) +
  640.         strlen(de->FileName) + 1);
  641.     de=next;
  642.     }
  643. }
  644.  
  645. void FixFile (struct IGRequest *req,struct IGFileRequest *fr)
  646. {
  647.     USHORT i;
  648.     struct StringInfo *info;
  649.  
  650.     info=(struct StringInfo *)fr->Gadgets[FILE].SpecialInfo;
  651.  
  652.     i=strlen (fr->FileName);
  653.     if (i>30) info->DispPos=i-30;
  654.     else info->DispPos=0;
  655.     info->BufferPos=i;
  656.     RefreshGList (&fr->Gadgets[FILE],req->Window,0,1);
  657. }
  658.  
  659. void GetFileName (UBYTE *pathfile,UBYTE *file)
  660. {
  661.     USHORT i;
  662.     i=strlen(pathfile);
  663.     while (i && pathfile[i]!=':' && pathfile[i]!='/') --i;
  664.     if (pathfile[i]==':' || pathfile[i]=='/') ++i;
  665.     strcpy (file,&pathfile[i]);
  666. }
  667.  
  668.  
  669. void FixDirNameEnding (UBYTE *dirname)
  670. {
  671.     USHORT i;
  672.  
  673.     i=strlen(dirname)-1;
  674.     if (dirname[i]!='/' && dirname[i]!=':') {
  675.     dirname[++i]='/';
  676.     dirname[++i]=0;
  677.     }
  678. }
  679.  
  680. void ChopLevel (UBYTE *FileName)
  681. {
  682.     USHORT i;
  683.  
  684.     i=strlen(FileName);
  685.     if (FileName[--i]==':') FileName[i]=0;
  686.     while (FileName[i]!='/' && FileName[i]!=':' && i) --i;
  687.     if (FileName[i]==':') ++i;
  688.     FileName[i]=0;
  689. }
  690.  
  691. void GetFRDirName (UBYTE *pathfile,UBYTE *file, struct IGFileRequest *fr)
  692. {
  693.     strcpy (file,pathfile);
  694.     if (fr->Flags & IGFR_FILENAMEPRESENT) ChopLevel(file);
  695. }
  696.  
  697. void UpDirectory (struct IGRequest *req,struct IGFileRequest *fr)
  698. {
  699.     ChopLevel (fr->FileName);
  700.     FixFile (req,fr);
  701. }
  702.  
  703. struct MsgPort *CreatePort ();
  704.  
  705. static VOID ShowDevices(struct IGRequest *req,struct IGFileRequest *fr)
  706. {
  707.     struct DosInfo *dosinfo;
  708.     struct DeviceList *masterlist, *devlist, *worklist;
  709.     struct MsgPort *handler;
  710.     LONG temp;
  711.     UBYTE *nameptr, *text;
  712.     UBYTE len;
  713.     SHORT i;
  714.     struct SelectBoxEntry *entry;
  715.  
  716.     if (DosBase == NULL) return ();
  717.  
  718.     ClearSBox (fr->SBox,0);
  719.     RefreshSBox (req,fr->SBox);
  720.  
  721.     fr->First=fr->DCEntry=0;
  722.  
  723.     fr->FileName[0]=0;
  724.     FixFile (req,fr);
  725.  
  726.     if (fr->Flags & IGFR_READING) {
  727.     fr->Flags^=IGFR_READING;
  728.     if (req->CallLoop & (1<<fr->CLBit)) req->CallLoop^=1<<fr->CLBit;
  729.     }
  730.     if (fr->Flags & IGFR_FILENAMEPRESENT)
  731.     fr->Flags^=IGFR_FILENAMEPRESENT;
  732.  
  733.     temp = (LONG)((struct RootNode *)DosBase->dl_Root)->rn_Info;
  734.     dosinfo = (struct DosInfo *)(temp << 2);        /* reality pointer */
  735.     temp = (LONG)dosinfo->di_DevInfo;
  736.     masterlist = (struct DeviceList *)(temp << 2);  /* reality pointer */
  737.  
  738.     devlist = masterlist;
  739.  
  740.  
  741.     while (devlist)
  742.     {
  743.     if (devlist->dl_Type==DLT_VOLUME || (devlist->dl_Type==DLT_DIRECTORY && fr->Flags & IGFR_INCLUDEASSIGNS)) {
  744.  
  745.         nameptr = (UBYTE *)devlist->dl_Name;
  746.  
  747. FoundName:  temp = (LONG)nameptr;
  748.         nameptr = (UBYTE *)(temp << 2);
  749.         len=*nameptr++;
  750.         if (!len) goto NextDevice;
  751.         text=AllocRemember (&fr->DirKey,len+2,MEMF_PUBLIC);
  752.         for (i=0;i<len;++i) text[i]=*nameptr++;
  753.         text[i++]=':';
  754.         text[i]=0;
  755.         entry=AllocRemember (&fr->DirKey,sizeof (struct SelectBoxEntry),MEMF_PUBLIC | MEMF_CLEAR);
  756.         entry->Text=text;
  757.         entry->Color=1;
  758.         AddSBEntryAlpha (fr->SBox,entry);
  759.     }
  760.  
  761. NextDevice: ;
  762.     temp = devlist->dl_Next;
  763.     devlist = (struct DeviceList *)(temp << 2);
  764.     }
  765.     RefreshSBox (req,fr->SBox);
  766. }
  767.  
  768. void ShowDir (struct IGRequest *req,struct IGFileRequest *fr)
  769. {
  770.     ClearSBox (fr->SBox,0);
  771.     RefreshSBox (req,fr->SBox);
  772.  
  773.     if (fr->Flags & IGFR_FILENAMEPRESENT) {
  774.     UpDirectory (req,fr);
  775.     fr->Flags^=IGFR_FILENAMEPRESENT;
  776.     }
  777.     if (fr->Flags & IGFR_READING) {
  778.     fr->Flags^=IGFR_READING;
  779.     if (req->CallLoop & (1<<fr->CLBit)) req->CallLoop^=1<<fr->CLBit;
  780.     UnLock (fr->Lock);
  781.     FreeMem (fr->FInfo,sizeof(struct FileInfoBlock));
  782.     fr->Lock=(BPTR)fr->FInfo=0;
  783.     }
  784.     if (!(fr->FileName[0])) goto devs;
  785.  
  786.     fr->FInfo=(struct FileInfoBlock *)AllocMem
  787.     (sizeof(struct FileInfoBlock),MEMF_PUBLIC | MEMF_CLEAR);
  788.     if (!(fr->FInfo)) goto devs;
  789.  
  790.     fr->Lock=Lock (fr->FileName,ACCESS_READ);
  791.  
  792. handlelock: ;
  793.     if (!(fr->Lock)) {
  794.     FreeMem (fr->FInfo,sizeof(struct FileInfoBlock));
  795.     fr->FInfo=0;
  796.     goto devs;
  797.     }
  798.  
  799.     Examine (fr->Lock,fr->FInfo);
  800.     if (fr->FInfo->fib_DirEntryType<0) {
  801.     UBYTE FName[200];
  802.     UnLock (fr->Lock);
  803.     if (fr->Flags & IGFR_MULTISELECT) {
  804.         ChopLevel (fr->FileName);
  805.         fr->Lock=Lock (fr->FileName,ACCESS_READ);
  806.         goto handlelock;
  807.     }
  808.     strcpy (FName,fr->FileName);
  809.     ChopLevel (FName);
  810.     fr->Lock=Lock (FName,ACCESS_READ);
  811.     goto handlelock;
  812.     } else {
  813.     fr->First=fr->DCEntry=0;
  814.     fr->Flags|=IGFR_READING | IGFR_FREEDIRKEY;
  815.     req->CallLoop|=1<<fr->CLBit;
  816.     }
  817.     return ();
  818. devs: ;
  819.     ShowDevices (req,fr);
  820. }
  821.  
  822. void SetDirectory (struct IGRequest *req,struct IGFileRequest *fr,UBYTE *dir)
  823. {
  824.     if (dir[0] && strcmp(fr->FileName,dir)) {
  825.     strcpy (fr->FileName,dir);
  826.     FLAGOFF(fr->Flags,IGFR_FILENAMEPRESENT);
  827.     FixFile (req,fr);
  828.     ShowDir (req,fr);
  829.     }
  830. }
  831.  
  832. static void FRLoop (struct IGRequest *);
  833. void ClearIGOServiced (struct IGRequest *);
  834.  
  835. BOOL SelectFile (struct IGRequest *req,struct IGFileRequest *fr,UBYTE *file)
  836. {
  837.     struct IGDirEntry *de;
  838.  
  839.     if (fr->Flags & IGFR_MULTISELECT) {
  840.     while (req->CallLoop & 1<<fr->CLBit) {
  841.         ClearIGOServiced (req);
  842.         FRLoop (req);
  843.     }
  844.     de=fr->First;
  845.     while (de && strcmp(de->FileName,file)) de=de->Next;
  846.     if (de && !(de->Flags & DIR) && !(de->Flags & SELECTED)) {
  847.         de->Flags|=SELECTED;
  848.         de->SBE->Flags|=SB_SELECTED;
  849.         RefreshSBox(req,fr->SBox);
  850.     } else return (1);
  851.     } else if (!(fr->Flags & IGFR_NOFILESELECT)) {
  852.     if (fr->Flags & IGFR_FILENAMEPRESENT)
  853.         UpDirectory (req,fr);
  854.     FixDirNameEnding (fr->FileName);
  855.     strcat (fr->FileName,file);
  856.     FixFile (req,fr);
  857.     fr->Flags|=IGFR_FILENAMEPRESENT;
  858.     }
  859.     return (0);
  860. }
  861.  
  862. void IGFRSelectAll (struct IGRequest *req, struct IGFileRequest *fr)
  863. {
  864.     struct IGDirEntry *de;
  865.  
  866.     if (fr->Flags & IGFR_MULTISELECT) {
  867.     while (req->CallLoop & 1<<fr->CLBit) {
  868.         ClearIGOServiced(req);
  869.         FRLoop (req);
  870.     }
  871.     for (de=fr->First;de;de=de->Next) {
  872.         if (!(de->Flags & SELECTED)) {
  873.         de->Flags|=SELECTED;
  874.         de->SBE->Flags|=SB_SELECTED;
  875.         }
  876.     }
  877.     RefreshSBox(req,fr->SBox);
  878.     }
  879. }
  880.  
  881. void IGFRDeSelectAll (struct IGRequest *req, struct IGFileRequest *fr)
  882. {
  883.     struct IGDirEntry *de;
  884.  
  885.     if (fr->Flags & IGFR_MULTISELECT) {
  886.     while(req->CallLoop & 1<<fr->CLBit) {
  887.         ClearIGOServiced(req);
  888.         FRLoop(req);
  889.     }
  890.     for (de=fr->First;de;de=de->Next) {
  891.         if (de->Flags & SELECTED) {
  892.         de->Flags^=SELECTED;
  893.         de->SBE->Flags^=SB_SELECTED;
  894.         }
  895.     }
  896.     RefreshSBox(req,fr->SBox);
  897.     } else if (fr->Flags & IGFR_FILENAMEPRESENT) UpDirectory(req,fr);
  898. }
  899.  
  900. BOOL SetPathFile (struct IGRequest *req,struct IGFileRequest *fr,UBYTE *path)
  901. {
  902.     BPTR lock;
  903.     struct FileInfoBlock fib;
  904.     UBYTE DirName[200];
  905.     UBYTE FName[50];
  906.  
  907.     lock=Lock(path,ACCESS_READ);
  908.     if (!lock) return (1);
  909.     Examine (lock,&fib);
  910.     UnLock (lock);
  911.  
  912.     strcpy (DirName,path);
  913.     if (fib.fib_DirEntryType<0) {
  914.     ChopLevel (DirName);
  915.     GetFileName (path,FName);
  916.     } else FName[0]=0;
  917.  
  918.     if (DirName[0]) SetDirectory (req,fr,DirName);
  919.     if (FName[0])
  920.     if (SelectFile (req,fr,FName)) return (1);;
  921.     return (0);
  922. }
  923.  
  924. static void Devices (struct IGRequest *req,struct IntuiMessage *msg)
  925. {
  926.     struct Gadget *gadg;
  927.     struct IGBoolInfo *iginfo;
  928.     struct IGFileRequest *fr;
  929.  
  930.     gadg=(struct Gadget *)msg->IAddress;
  931.     iginfo=(struct IGBoolInfo *)gadg->UserData;
  932.     fr=(struct IGFileRequest *)iginfo->IGObject->Address;
  933.     ShowDevices (req,fr);
  934. }
  935.  
  936. static void ParentDirectory (struct IGRequest *req,struct IntuiMessage *msg)
  937. {
  938.     struct Gadget *gadg;
  939.     struct IGBoolInfo *iginfo;
  940.     struct IGFileRequest *fr;
  941.  
  942.     gadg=(struct Gadget *)msg->IAddress;
  943.     iginfo=(struct IGBoolInfo *)gadg->UserData;
  944.     fr=iginfo->IGObject->Address;
  945.     UpDirectory (req,fr);
  946.     ShowDir (req,fr);
  947. }
  948.  
  949. static BOOL MatchExtension (UBYTE *name,UBYTE *ext)
  950. {
  951.     USHORT l,p;
  952.  
  953.     p=strlen (name);
  954.     l=strlen (ext);
  955.     p-=l;
  956.     if (!stricmp (&name[p],ext)) return (1);
  957.     return (0);
  958. }
  959.  
  960. static void NewExtReal (struct IGRequest *req,struct IGFileRequest *fr);
  961.  
  962. static void FRLoop (struct IGRequest *req)
  963. {
  964.     struct IGObject *obj;
  965.     struct IGFileRequest *fr;
  966.     struct IGPropInfo *pinfo;
  967.     struct Gadget *prop;
  968.     struct IGSBoxGadgetInfo *ginfo;
  969.     char *s;
  970.     USHORT i,x;
  971.  
  972.     for (obj=req->IGObjects;obj->Next;obj=obj->Next);
  973.  
  974.     while (obj->Serviced || strcmp (obj->Class,"IGFileRequest")) obj=obj->Prev;
  975.  
  976.     obj->Serviced=1;
  977.  
  978.     fr=(struct IGFileRequest *)obj->Address;
  979.     prop=&fr->Gadgets[SCROLL];
  980.     pinfo=(struct IGPropInfo *)prop->UserData;
  981.     ginfo=(struct IGSBoxGadgetInfo *)fr->SBox->GList->UserData;
  982.  
  983.     if (fr->Flags & IGFR_FREEDIRKEY) {
  984.     fr->Flags^=IGFR_FREEDIRKEY;
  985.     FreeRemember (&fr->DirKey,1);
  986.     fr->Number=0;
  987.     }
  988.     if (fr->Flags & IGFR_INIT) {
  989.     fr->Flags^=IGFR_INIT;
  990.     req->CallLoop^=1<<fr->CLBit;
  991.     if (fr->FileName[0]) {
  992.         if (fr->Flags & IGFR_VARSSAVED) {
  993.         fr->Flags^=IGFR_VARSSAVED;
  994.         NewExtReal (req,fr);
  995.         if (fr->Flags & IGFR_READING) req->CallLoop|=1<<fr->CLBit;
  996.         } else {
  997.         ShowDir (req,fr);
  998.         }
  999.     } else ShowDevices (req,fr);
  1000.     } else if (fr->Flags & IGFR_READING) {
  1001.     if (!ExNext (fr->Lock,fr->FInfo)) {
  1002.         FreeMem (fr->FInfo,sizeof (struct FileInfoBlock));
  1003.         fr->FInfo=0;
  1004.         UnLock (fr->Lock);
  1005.         fr->Lock=0;
  1006.         fr->Flags^=IGFR_READING;
  1007.         req->CallLoop^=1<<fr->CLBit;
  1008.         RefreshSBox (req,fr->SBox);
  1009.     } else {
  1010.         UBYTE  infoflag=0;
  1011.         struct SelectBoxEntry *item;
  1012.         struct IGDirEntry *de,*ix;
  1013.  
  1014.         ++fr->Number;
  1015.         de=(struct IGDirEntry *)AllocRemember (&fr->DirKey,
  1016.         sizeof (struct IGDirEntry),MEMF_PUBLIC);
  1017.         de->FileName=(UBYTE *)AllocRemember(&fr->DirKey,
  1018.         strlen(fr->FInfo->fib_FileName)+1,MEMF_PUBLIC);
  1019.         item=de->SBE=(struct SelectBoxEntry *)AllocRemember (&fr->DirKey,
  1020.         sizeof(struct SelectBoxEntry),MEMF_PUBLIC | MEMF_CLEAR);
  1021.         s=(UBYTE *)AllocRemember (&fr->DirKey,
  1022.         strlen(fr->FInfo->fib_FileName)+8,MEMF_PUBLIC);
  1023.         strcpy (de->FileName,fr->FInfo->fib_FileName);
  1024.         strcpy (s,de->FileName);
  1025.  
  1026.         item->Text=s;
  1027.         item->IGObject=obj;
  1028.         item->UserData=(APTR)de;
  1029.         item->Color=1;
  1030.  
  1031.         de->Flags=0;
  1032.  
  1033.         if (fr->FInfo->fib_DirEntryType>0) {
  1034.         strcat (s," (DIR)");
  1035.         de->Flags=DIR | DISPLAYED;
  1036.  
  1037.         ix=fr->First;
  1038.         if (!ix) {
  1039.             de->Next=de->Prev=0;
  1040.         } else {
  1041.             if (!(ix->Flags & DIR)) {
  1042.             de->Next=ix;
  1043.             de->Prev=0;
  1044.             ix->Prev=de;
  1045.             } else {
  1046.             while (ix->Next && stricmp(ix->FileName,de->FileName)<0 && ix->Flags & DIR)
  1047.                 ix=ix->Next;
  1048.             if (!(ix->Next) && stricmp (ix->FileName,de->FileName)<0 && ix->Flags & DIR) {
  1049.                 ix->Next=de;
  1050.                 de->Prev=ix;
  1051.                 de->Next=0;
  1052.             } else {
  1053.                 de->Next=ix;
  1054.                 de->Prev=ix->Prev;
  1055.                 if (ix->Prev) ix->Prev->Next=de;
  1056.                 ix->Prev=de;
  1057.             }
  1058.             }
  1059.         }
  1060.         if (!(de->Prev)) fr->First=de;
  1061.         if (de->Prev) AddSBEntry (fr->SBox,de->SBE,de->Prev->SBE->ID+2);
  1062.         else AddSBEntry (fr->SBox,de->SBE,1);
  1063.         ModifyIGProp (req,prop,0,fr->Number,0,7,pinfo->Top,0);
  1064.         ginfo->Entry=de->SBE;
  1065.         } else {
  1066.         if (fr->Flags & IGFR_NOFILESELECT) item->Color=2;
  1067.         ix=fr->First;
  1068.         if (!ix) {
  1069.             de->Next=de->Prev=0;
  1070.         } else {
  1071.             while (ix->Next && ix->Flags & DIR) ix=ix->Next;
  1072.             if (!(ix->Next) && ix->Flags & DIR) {
  1073.             ix->Next=de;
  1074.             de->Prev=ix;
  1075.             de->Next=0;
  1076.             } else {
  1077.             while (ix->Next && stricmp(ix->FileName,de->FileName)<0)
  1078.                 ix=ix->Next;
  1079.             if (!(ix->Next) && stricmp(ix->FileName,de->FileName)<0) {
  1080.                 ix->Next=de;
  1081.                 de->Prev=ix;
  1082.                 de->Next=0;
  1083.             } else {
  1084.                 de->Next=ix;
  1085.                 de->Prev=ix->Prev;
  1086.                 if (ix->Prev) ix->Prev->Next=de;
  1087.                 ix->Prev=de;
  1088.             }
  1089.             }
  1090.         }
  1091.         if (!(de->Prev)) fr->First=de;
  1092.  
  1093.         if ((fr->Flags & IGFR_NOINFO) &&
  1094.           MatchExtension (de->FileName,".info"))
  1095.             infoflag=1;
  1096.         if (!infoflag && MatchExtension (de->FileName,fr->Extension)) {
  1097.             de->Flags=DISPLAYED;
  1098.             ix=de->Prev;
  1099.             while (ix && !(ix->Flags & DISPLAYED)) ix=ix->Prev;
  1100.             if (!ix) AddSBEntry (fr->SBox,de->SBE,1);
  1101.             else AddSBEntry (fr->SBox,de->SBE,ix->SBE->ID+2);
  1102.             ModifyIGProp (req,prop,0,fr->Number,0,7,pinfo->Top,0);
  1103.             ginfo->Entry=de->SBE;
  1104.         }
  1105.         }
  1106.     }
  1107.     }
  1108.     if (fr->LoopFunction) (*(fr->LoopFunction)) (req);
  1109. }
  1110.  
  1111.  
  1112. static void NewExtReal (struct IGRequest *req,struct IGFileRequest *fr)
  1113. {
  1114.     struct IGDirEntry *de;
  1115.     USHORT i;
  1116.  
  1117.     ClearSBox (fr->SBox,0);
  1118.     RefreshSBox (req,fr->SBox);
  1119.     fr->DCEntry=0;
  1120.  
  1121.     for (i=1,de=fr->First;de;de=de->Next) {
  1122.     if (de->Flags & DISPLAYED) de->Flags^=DISPLAYED;
  1123.     if (de->Flags & DIR) {
  1124.         AddSBEntry (fr->SBox,de->SBE,i++);
  1125.         de->Flags|=DISPLAYED;
  1126.     } else if (MatchExtension (de->FileName,fr->Extension)) {
  1127.         AddSBEntry (fr->SBox,de->SBE,i++);
  1128.         de->Flags|=DISPLAYED;
  1129.     }
  1130.     }
  1131.     RefreshSBox (req,fr->SBox);
  1132. }
  1133.  
  1134. static void NewExt (struct IGReqeust *req,struct IntuiMessage *msg)
  1135. {
  1136.     struct Gadget *gadg;
  1137.     struct IGStringInfo *iginfo;
  1138.     struct IGFileRequest *fr;
  1139.  
  1140.     gadg=(struct Gadget *)msg->IAddress;
  1141.     iginfo=(struct IGStringInfo *)gadg->UserData;
  1142.     fr=(struct IGFileRequest *)iginfo->IGObject->Address;
  1143.  
  1144.     NewExtReal (req,fr);
  1145. }
  1146.  
  1147. static void TypedDir (struct IGRequest *req,struct IntuiMessage *msg)
  1148. {
  1149.     struct Gadget *gadg;
  1150.     struct IGStringInfo *iginfo;
  1151.     struct IGFileRequest *fr;
  1152.  
  1153.     gadg=(struct Gadget *)msg->IAddress;
  1154.     iginfo=(struct IGBoolInfo *)gadg->UserData;
  1155.     fr=(struct IGFileRequest *)iginfo->IGObject->Address;
  1156.  
  1157.     ShowDir (req,fr);
  1158. }
  1159.  
  1160. static void HandleSelection (struct IGRequest *req,
  1161.               struct SelectBox *sbox,
  1162.               struct SelectBoxEntry *entry,
  1163.               struct IntuiMessage *msg)
  1164. {
  1165.     struct IGDirEntry *de;
  1166.     struct IGFileRequest *fr;
  1167.     USHORT i;
  1168.     UBYTE dcf=0;
  1169.  
  1170.     fr=(struct IGFileRequest *)sbox->IGObject->Address;
  1171.     de=(struct IGDirEntry *)entry->UserData;
  1172.  
  1173.     if (fr->DCEntry==de)
  1174.     if (DoubleClick (fr->DCSecs,fr->DCMics,msg->Seconds,msg->Micros))
  1175.         dcf=1;
  1176.     if (!dcf) {
  1177.     fr->DCEntry=de;
  1178.     fr->DCSecs=msg->Seconds;
  1179.     fr->DCMics=msg->Micros;
  1180.     }
  1181.  
  1182.     if (!de) {
  1183.     strcpy (fr->FileName,entry->Text);
  1184.     FixFile (req,fr);
  1185.     ShowDir (req,fr);
  1186.     } else if (de->Flags & DIR) {
  1187.     if (!(fr->Flags & IGFR_MULTISELECT) || dcf) {
  1188.         if (fr->Flags & IGFR_FILENAMEPRESENT) {
  1189.         UpDirectory (req,fr);
  1190.         fr->Flags^=IGFR_FILENAMEPRESENT;
  1191.         }
  1192.         FixDirNameEnding (fr->FileName);
  1193.         strcat (fr->FileName,de->FileName);
  1194.         FixFile (req,fr);
  1195.         ShowDir (req,fr);
  1196.     } else de->Flags^=SELECTED;
  1197.     } else {
  1198.     if (!(fr->Flags & IGFR_NOFILESELECT)) {
  1199.         if (fr->Flags & IGFR_MULTISELECT)
  1200.         de->Flags^=SELECTED;
  1201.         else {
  1202.         if (dcf) {
  1203.             msg->IAddress=&fr->Gadgets[OK];
  1204.             IGFRQuit (req,msg);
  1205.             return ();
  1206.         }
  1207.         if (fr->Flags & IGFR_FILENAMEPRESENT) UpDirectory (req,fr);
  1208.         i=strlen (fr->FileName)-1;
  1209.         if (!(fr->FileName[i]=='/' || fr->FileName[i]==':')) {
  1210.             fr->FileName[++i]='/';
  1211.             fr->FileName[++i]=0;
  1212.         }
  1213.         strcat (fr->FileName,de->FileName);
  1214.         fr->Flags|=IGFR_FILENAMEPRESENT;
  1215.         FixFile (req,fr);
  1216.         }
  1217.     }
  1218.     }
  1219. }
  1220.  
  1221. static void DiskChanged (struct IGRequest *req,struct IntuiMessage *msg)
  1222. {
  1223.     struct IGFileRequest *fr;
  1224.     struct IGObject *obj;
  1225.  
  1226.     for (obj=req->IGObjects;obj->Next;obj=obj->Next);
  1227.     while (obj->Serviced || strcmp (obj->Class,"IGFileRequest")) obj=obj->Prev;
  1228.  
  1229.     obj->Serviced=1;
  1230.     fr=(struct IGFileRequest *)obj->Address;
  1231.     if (!(fr->FileName[0])) ShowDevices (req,fr);
  1232.     if (msg->Class & IDCMP_DISKINSERTED) {
  1233.     if(fr->DInserted) (*(fr->DInserted)) (req,msg);
  1234.     } else if (fr->DRemoved) (*(fr->DRemoved)) (req,msg);
  1235. }
  1236.  
  1237. static void IGFRQuit (struct IGRequest *req,struct IntuiMessage *msg)
  1238. {
  1239.     struct Gadget *gadg;
  1240.     struct IGBoolInfo *info;
  1241.     struct IGFileRequest *fr;
  1242.  
  1243.     gadg=(struct Gadget *)msg->IAddress;
  1244.     info=(struct IGBoolInfo *)gadg->UserData;
  1245.     fr=(struct IGFileRequest *)info->IGObject->Address;
  1246.  
  1247.     if (gadg==&fr->Gadgets[OK]) req->Terminate=1;
  1248.     else req->Terminate=-1;
  1249. }
  1250.  
  1251. static void KillIGFileRequest (struct IGRequest *req,struct IGObject *obj,APTR ignore)
  1252. {
  1253.     USHORT i;
  1254.     struct IGFileRequest *fr;
  1255.     struct SelectBoxEntry *e,*nxt;
  1256.  
  1257.     fr=(struct IGFileRequest *)obj->Address;
  1258.  
  1259.     if (!(fr->Flags & IGFR_MULTISELECT)) {
  1260.     FreeRemember (&fr->DirKey,1);
  1261.     fr->First=0;
  1262.     }
  1263.  
  1264.     fr->DCEntry=0;
  1265.     if (fr->Lock) UnLock (fr->Lock);
  1266.     if (fr->FInfo) FreeMem (fr->FInfo,sizeof (struct FileInfoBlock));
  1267.     fr->Lock=fr->FInfo=0;
  1268.  
  1269.     if (fr->Gadgets)
  1270.     for (i=0;i<9;++i) {
  1271.         if ((i==OK || i==CANCEL) && !(fr->Flags & IGFR_OKCANCEL)) continue;
  1272.         IGRemoveGadget (req,&fr->Gadgets[i]);
  1273.     }
  1274.     if (fr->Borders) {
  1275.     IGRemoveBorder (req,fr->Borders->NextBorder);
  1276.     IGRemoveBorder (req,fr->Borders);
  1277.     }
  1278.     if (fr->SBox) IGRemoveSBox (req,fr->SBox);
  1279.     FreeRemember (&fr->Key,1);
  1280.     if ( req->CallLoop & (1<<fr->CLBit) ) req->CallLoop ^= 1 << fr->CLBit;
  1281.     FreeCLBit (req,fr->CLBit);
  1282.     fr->TopEdge-=obj->GadgetYOffSet;
  1283.     req->LoopFunction=fr->LoopFunction;
  1284.     req->DiskRemoved=fr->DRemoved;
  1285.     req->DiskInserted=fr->DInserted;
  1286. }
  1287.  
  1288. BOOL MakeIGFileRequest (struct IGRequest *req,struct IGObject *obj)
  1289. {
  1290.     struct IGFileRequest *fr;
  1291.     USHORT i;
  1292.  
  1293.     fr=(struct IGFileRequest *)obj->Address;
  1294.     if (!fr) goto error;
  1295.     fr->TopEdge+=obj->GadgetYOffSet;
  1296.  
  1297.     fr->Gadgets=fr->SBox=fr->Borders=0;
  1298.     fr->Flags &= (1 | 4 | 16 | 64 | 128 | 256 | 512 | 1024);
  1299.     obj->Class=(UBYTE *)"IGFileRequest";
  1300.     fr->Flags|=IGFR_INIT;
  1301.     fr->CLBit=AllocCLBit (req);
  1302.     if (fr->CLBit==-1) goto error;
  1303.  
  1304.     req->CallLoop|=1<<fr->CLBit;
  1305.  
  1306.      /* These are first so that we know */
  1307.      /* Even on error, that they have */
  1308.      /* Been Changed. */
  1309.  
  1310.     fr->LoopFunction=req->LoopFunction;
  1311.     req->LoopFunction=FRLoop;
  1312.     fr->DInserted=req->DiskInserted;
  1313.     fr->DRemoved=req->DiskRemoved;
  1314.     req->DiskInserted=req->DiskRemoved=DiskChanged;
  1315.  
  1316.     obj->AbortFunction=obj->RequestEndedFunction=KillIGFileRequest;
  1317.  
  1318.     fr->Gadgets=AllocRemember (&fr->Key,sizeof (struct Gadget)*9,MEMF_PUBLIC);
  1319.     fr->SBox=AllocRemember (&fr->Key,sizeof (struct SelectBox),MEMF_PUBLIC |
  1320.     MEMF_CLEAR);
  1321.     fr->Borders=AllocRemember (&fr->Key,sizeof (struct Border)*2,MEMF_PUBLIC);
  1322.  
  1323.     if (!(fr->Gadgets) || !(fr->SBox) || !(fr->Borders)) goto error;
  1324.  
  1325.  
  1326.     fr->Borders[0]=IGFRBoxB1;
  1327.     fr->Borders[1]=IGFRBoxB2;
  1328.     fr->Borders[0].NextBorder=&fr->Borders[1];
  1329.     fr->Borders[0].FrontPen=fr->BColor2;
  1330.     fr->Borders[1].FrontPen=fr->BColor1;
  1331.     fr->Borders[0].LeftEdge=fr->Borders[1].LeftEdge+=fr->LeftEdge-5;
  1332.     fr->Borders[0].TopEdge=fr->Borders[1].TopEdge+=fr->TopEdge-12;
  1333.     fr->Borders[1].NextBorder=req->Borders;
  1334.     req->Borders=fr->Borders;
  1335.  
  1336.     fr->SBox->LeftEdge=4+fr->LeftEdge;
  1337.     fr->SBox->TopEdge=4+fr->TopEdge;
  1338.     fr->SBox->Width=284;
  1339.     fr->SBox->Displayed=7;
  1340.     fr->SBox->BColor1=fr->BColor1;
  1341.     fr->SBox->BColor2=fr->BColor2;
  1342.     fr->SBox->Prop=&fr->Gadgets[SCROLL];
  1343.     fr->SBox->ItemSelected=fr->SBox->ItemDSelected=HandleSelection;
  1344.     fr->SBox->Flags=fr->Flags & IGFR_MULTISELECT ? SB_TOGGLEALL : SB_RELVERIFY;
  1345.     fr->SBox->IGObject=obj;
  1346.     fr->SBox->Next=req->SBoxes;
  1347.     req->SBoxes=fr->SBox;
  1348.  
  1349.     fr->Gadgets[DEVS]=IGFRDevs;
  1350.     fr->Gadgets[PARENT]=IGFRParent;
  1351.     fr->Gadgets[OK]=IGFROK;
  1352.     fr->Gadgets[CANCEL]=IGFRCancel;
  1353.     fr->Gadgets[EXT]=IGFRExt;
  1354.     fr->Gadgets[FILE]=IGFRFName;
  1355.  
  1356.     fr->Gadgets[UP]=IGFRScrollUpArrowGad;
  1357.     fr->Gadgets[DOWN]=IGFRScrollDownArrowGad;
  1358.     IGFRScrollDownArrowImage.ImageData = DownArrowData;
  1359.     IGFRScrollUpArrowImage.ImageData = UpArrowData;
  1360.  
  1361.     fr->Gadgets[SCROLL]=IGFRScroll;
  1362.  
  1363.     for (i=0;i<4;++i) {
  1364.     struct IGBoolInfo *info;
  1365.     info=(struct IGBoolInfo *)fr->Gadgets[i].UserData=AllocRemember
  1366.         (&fr->Key,sizeof (struct IGBoolInfo),MEMF_PUBLIC | MEMF_CLEAR);
  1367.     if (!info) goto error;
  1368.     info->Type=GADG_BOOL;
  1369.     info->IGObject=obj;
  1370.     switch (i) {
  1371.         case DEVS:        info->GUpFunction=Devices;
  1372.                 break;
  1373.         case PARENT:    info->GUpFunction=ParentDirectory;
  1374.                 break;
  1375.         case OK:        info->GUpFunction=IGFRQuit;
  1376.                 break;
  1377.         case CANCEL:    info->GUpFunction=IGFRQuit;
  1378.                 break;
  1379.     }
  1380.     }
  1381.  
  1382.     for (i=4;i<6;++i) {
  1383.     struct IGStringInfo *info;
  1384.     struct StringInfo *sinfo;
  1385.  
  1386.     info=(struct IGStringInfo *)fr->Gadgets[i].UserData=AllocRemember
  1387.         (&fr->Key,sizeof (struct IGStringInfo),MEMF_PUBLIC | MEMF_CLEAR);
  1388.     sinfo=(struct StringInfo *)fr->Gadgets[i].SpecialInfo=AllocRemember
  1389.         (&fr->Key,sizeof (struct StringInfo),MEMF_PUBLIC | MEMF_CLEAR);
  1390.     if (!info || !sinfo) goto error;
  1391.     info->Type=GADG_STRING;
  1392.     info->IGObject=obj;
  1393.     if (i==EXT) {
  1394.         info->DisAllowedChars="/:";
  1395.         sinfo->MaxChars=10;
  1396.         sinfo->Buffer=fr->Extension;
  1397.         info->DSelectFunction=NewExt;
  1398.     } else {
  1399.         sinfo->MaxChars=200;
  1400.         sinfo->Buffer=fr->FileName;
  1401.         info->DSelectFunction=TypedDir;
  1402.     }
  1403.     }
  1404.  
  1405.     {
  1406.     struct PropInfo *info;
  1407.     struct IGPropInfo *iginfo;
  1408.  
  1409.     info=AllocRemember
  1410.         (&fr->Key,sizeof (struct PropInfo),MEMF_PUBLIC);
  1411.     fr->Gadgets[SCROLL].GadgetRender=AllocRemember (&fr->Key,8,MEMF_PUBLIC | MEMF_CLEAR);
  1412.     iginfo=AllocRemember (&fr->Key,
  1413.         sizeof (struct IGPropInfo),MEMF_PUBLIC | MEMF_CLEAR);
  1414.     if (!info || !(fr->Gadgets[SCROLL].GadgetRender) || !iginfo) goto error;
  1415.     fr->Gadgets[SCROLL].SpecialInfo=(APTR)info;
  1416.     fr->Gadgets[SCROLL].UserData=(APTR)iginfo;
  1417.     *info=IGFRScrollPropInfo;
  1418.     iginfo->Type=GADG_PROP;
  1419.     iginfo->DisplayedY=7;
  1420.     iginfo->ScrollFunc=UpdateSBox;
  1421.     iginfo->LUArrow=&fr->Gadgets[UP];
  1422.     iginfo->RDArrow=&fr->Gadgets[DOWN];
  1423.     iginfo->SBox=fr->SBox;
  1424.     iginfo->IGObject=obj;
  1425.     }
  1426.  
  1427.     for (i=6;i<8;++i) {
  1428.     struct IGPropArrowInfo *info;
  1429.  
  1430.     info=AllocRemember
  1431.         (&fr->Key,sizeof (struct IGPropArrowInfo),MEMF_PUBLIC | MEMF_CLEAR);
  1432.     if (!info) goto error;
  1433.     fr->Gadgets[i].UserData=(APTR)info;
  1434.     info->Type=GADG_ARROW;
  1435.     info->Prop=&fr->Gadgets[SCROLL];
  1436.     info->IGObject=obj;
  1437.     }
  1438.     for (i=0;i<9;++i) {
  1439.     fr->Gadgets[i].LeftEdge+=fr->LeftEdge-5;
  1440.     fr->Gadgets[i].TopEdge+=fr->TopEdge-12;
  1441.     fr->Gadgets[i].NextGadget=&fr->Gadgets[i+1];
  1442.     }
  1443.     fr->Gadgets[8].NextGadget=req->Gadgets;
  1444.     if (!(fr->Flags & IGFR_OKCANCEL))
  1445.     fr->Gadgets[OK-1].NextGadget=&fr->Gadgets[CANCEL+1];
  1446.     req->Gadgets=fr->Gadgets;
  1447.  
  1448.     return (0);
  1449.  
  1450. error: return (1);
  1451. }
  1452.  
  1453.